package com.stack.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Decoder;

import javax.imageio.stream.FileImageOutputStream;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;

/**
 * 
 * 版权所有：2016 项目名称：ImgeBase64
 *
 * 类描述：将图片转化为Base64字符串 类名称：cn.sanishan.util.Base64Img 创建人： 创建时间：2016年10月27日
 * 下午3:25:49 修改人： 修改时间：2016年10月27日 下午3:25:49 修改备注：
 * 
 * @version V1.0
 */
public class Base64ImgUtil {

	private static final Logger logger = LoggerFactory.getLogger(Base64ImgUtil.class);

	private static final int PROTECTED_LENGTH = 4 * 1024 * 1024;// 输入流保护 1M

	/**
	 * @Title: GetImageStrFromUrl
	 * @Description: TODO(将一张网络图片转化成Base64字符串)
	 * @param imgURL
	 *            网络资源位置
	 * @return Base64字符串
	 */
	public static String getImageStrFromUrl(String imgURL) {
	     return "data:image/jpeg;base64," + new String(Base64.getEncoder().encode(getImageStrFromUrlToSourceByte(imgURL)));
	}

	/**
	 * @Title: GetImageStrFromUrl
	 * @Description: TODO(将一张网络图片转化成Base64字符串)
	 * @param imgURL
	 *            网络资源位置
	 * @return Base64字符串
	 */
	public static String getImageStrFromUrlWithoutHead(String imgURL) {
		return new String(Base64.getEncoder().encode(getImageStrFromUrlToSourceByte(imgURL)));
	}

	/**
	 * 生成图片的原始字节数组
	 * @param imgURL
	 * @return
	 */
	public static byte[] getImageStrFromUrlToSourceByte(String imgURL) {
		byte[] data = null;
		InputStream inStream = null;
		try {
			// 创建URL
			URL url = new URL(imgURL);
			// 创建链接
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setRequestMethod("GET");
			conn.setConnectTimeout(5 * 1000);
			inStream = conn.getInputStream();

			if (inStream == null) {
				return null;
			}
		} catch (IOException e) {
			logger.error(e.getMessage());
		}

		// 字节数组
		byte[] bCache = new byte[2048];
		int readSize = 0;// 每次读取的字节长度
		int totalSize = 0;// 总字节长度
		ByteArrayOutputStream infoStream = new ByteArrayOutputStream();
		try {
			// 一次性读取2048字节
			while ((readSize = inStream.read(bCache)) > 0) {
				totalSize += readSize;
				if (totalSize > PROTECTED_LENGTH) {

					logger.error("输入流超出1M大小限制");
					return null;
				}
				// 将bcache中读取的input数据写入infoStream
				infoStream.write(bCache, 0, readSize);
			}
		} catch (IOException e1) {
			logger.error("输入流读取异常");
			return null;
		} finally {
			try {
				if (inStream != null) {
					inStream.close();
				}
			} catch (IOException e) {
				logger.error("输入流关闭异常");
			}
		}
		return infoStream.toByteArray();
	}

	/**
	 * @Title: GetImageStrFromPath
	 * @Description: TODO(将一张本地图片转化成Base64字符串)
	 * @param imgPath
	 * @return
	 */
	public static String getImageStrFromPath(String imgPath) {
		InputStream in = null;
		byte[] data = null;
		// 读取图片字节数组
		try {
			in = new FileInputStream(imgPath);
			data = new byte[in.available()];
			in.read(data);
			in.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 返回Base64编码过的字节数组字符串
		return new String(Base64.getEncoder().encode(data));
	}

	public static byte[] getImageStrFromPathToSourceByte(String imgPath) {
		InputStream inStream = null;
		byte[] data = null;

		// 字节数组
		byte[] bCache = new byte[2048];
		int readSize = 0;// 每次读取的字节长度
		int totalSize = 0;// 总字节长度
		ByteArrayOutputStream infoStream = new ByteArrayOutputStream();
		try {
			inStream = new FileInputStream(imgPath);
			// 一次性读取2048字节
			while ((readSize = inStream.read(bCache)) > 0) {
				totalSize += readSize;
				if (totalSize > PROTECTED_LENGTH) {

					logger.error("输入流超出1M大小限制");
					return null;
				}
				// 将bcache中读取的input数据写入infoStream
				infoStream.write(bCache, 0, readSize);
			}
		} catch (IOException e1) {
			logger.error("输入流读取异常");
			return null;
		} finally {
			try {
				if (inStream != null) {
					inStream.close();
				}
			} catch (IOException e) {
				logger.error("输入流关闭异常");
			}
		}
		return infoStream.toByteArray();
	}

	/**
	 * @Title: GenerateImage
	 * @Description: TODO(base64字符串转化成图片)
	 * @param imgStr
	 * @return
	 */
	public static boolean generateImage(String imgStr) {
		// 图像数据为空
		if (imgStr == null) {
			return false;
		}

		try {
			// Base64解码
			byte[] b = Base64.getDecoder().decode(imgStr);
			for (int i = 0; i < b.length; ++i) {
				if (b[i] < 0) {// 调整异常数据
					b[i] += 256;
				}
			}
			// 生成jpeg图片
			String imgFilePath = "C:/Users/112/Pictures/保存/新图片.jpg";
			OutputStream out = new FileOutputStream(imgFilePath);
			out.write(b);
			out.flush();
			out.close();
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	public static boolean generateImage(String imgStr, String target) {
		// 图像数据为空
		if (imgStr == null) {
			return false;
		}

		try (
				OutputStream out = Files.newOutputStream(Paths.get(target))
		) {
			// Base64解码
			byte[] b = new BASE64Decoder().decodeBuffer(imgStr);
			for (int i = 0; i < b.length; ++i) {
				if (b[i] < 0) {// 调整异常数据
					b[i] += 256;
				}
			}
			// 生成jpeg图片
			out.write(b);
			out.flush();
			return true;
		} catch (Exception e) {
			return false;
		}
	}
	
	/**
	 * 切割
	 * @param base url
	 * @param symbol 切割符
	 * @return
	 */
	public static String[] urlCutting(String base, String symbol) {
		String[] se = base.split(symbol);
		return se;
	}

	private static byte[] getImageToByte(String imgPath) {
		InputStream in = null;
		byte[] data = null;
		// 读取图片字节数组
		try {
			in = new FileInputStream(imgPath);
			data = new byte[in.available()];
			in.read(data);
			in.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return data;
	}

	public static String getByteToImage(String path, byte[] b, int offset, int length) {
		FileImageOutputStream outputStream = null;
		try {
			outputStream = new FileImageOutputStream(new File(path));
			outputStream.write(b, offset, length);
			return path;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (outputStream != null) {
					outputStream.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	public static Integer imageSize(String imageBase64Str) {
		int equalIndex = imageBase64Str.indexOf("=");
		if (equalIndex > 0) {
			imageBase64Str = imageBase64Str.substring(0, equalIndex);
		}
		int strLength = imageBase64Str.length();
		return strLength - (strLength/8)*2;	//单位字节
	}

	public static Double imageSizeToKb(String imageBase64Str) {
		BigDecimal kilobyte = new BigDecimal(1024);
		BigDecimal fileSize = new BigDecimal(imageSize(imageBase64Str));
		return fileSize.divide(kilobyte, 1, RoundingMode.DOWN).doubleValue();
	}

	public static String imageType(String imageBase64Str) {
		if (imageBase64Str.contains("data:")) {
			int headIndex = imageBase64Str.indexOf(",");
			imageBase64Str = imageBase64Str.substring(headIndex+1);
		}
		String type = null;
		try {
			byte[] b = Base64.getDecoder().decode(imageBase64Str);
			if (0x424D == ((b[0] & 0xff) << 8 | (b[1] & 0xff))) {
				type = "bmp";
			} else if (0x8950 == ((b[0] & 0xff) << 8 | (b[1] & 0xff))) {
				type = "png";
			} else if (0xFFD8 == ((b[0] & 0xff) << 8 | (b[1] & 0xff))
					|| 0x5249 == ((b[0] & 0xff) << 8 | (b[1] & 0xff))) {
				type = "jpg";
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return type;
	}

	public static byte[] getImageByteFromUrl(String imgURL) {
		try {
			URL url = new URL(imgURL);
			// 创建链接
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setRequestMethod("GET");
			conn.setConnectTimeout(5 * 1000);
			try (
					InputStream inStream = conn.getInputStream();
					ByteArrayOutputStream outStream = new ByteArrayOutputStream();
			) {
				// 字节数组
				byte[] bCache = new byte[2048];
				int readSize = 0;// 每次读取的字节长度
				int totalSize = 0;// 总字节长度
				// 一次性读取2048字节
				while ((readSize = inStream.read(bCache)) > 0) {
					totalSize += readSize;
					if (totalSize > PROTECTED_LENGTH) {
						logger.error("输入流超出1M大小限制");
						return null;
					}
					// 将bcache中读取的input数据写入infoStream
					outStream.write(bCache, 0, readSize);
				}
				return outStream.toByteArray();
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

}
